package utils

import (
	"database/sql"
	"gitee.com/chejiangyi/bsfgo/core/base2"
	"github.com/jinzhu/copier"
	"go/types"
	"golang.org/x/tools/go/packages"
	"reflect"
)

var ReflectUtil = &ReflectUtilTool{}

type ReflectUtilTool struct{}

func (*ReflectUtilTool) RowsToMap(rows *sql.Rows) ([]map[string]interface{}, error) {
	columns, err := rows.Columns()
	if err != nil {
		return nil, err
	}
	var results []map[string]interface{}
	for rows.Next() {
		// 创建值的切片和指针切片
		values := make([]interface{}, len(columns))
		pointers := make([]interface{}, len(columns))
		for i := range values {
			pointers[i] = &values[i]
		}
		// 扫描行数据到指针切片
		if err := rows.Scan(pointers...); err != nil {
			return nil, err
		}
		// 创建当前行的map
		rowMap := make(map[string]interface{})
		for i, colName := range columns {
			val := values[i]
			// 处理可能的 NULL 值
			if val == nil {
				rowMap[colName] = nil
			} else {
				// 根据实际类型处理
				switch v := val.(type) {
				case []byte:
					rowMap[colName] = string(v)
				default:
					rowMap[colName] = v
				}
			}
		}
		results = append(results, rowMap)
	}
	if err = rows.Err(); err != nil {
		return nil, err
	}
	return results, nil
}

func (*ReflectUtilTool) StructToMap(obj interface{}) map[string]interface{} {
	out := make(map[string]interface{})
	v := reflect.ValueOf(obj)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	if v.Kind() != reflect.Struct {
		panic(base2.NewBsfError("输入必须是结构体或结构体指针"))
	}

	t := v.Type()
	for i := 0; i < v.NumField(); i++ {
		field := t.Field(i)
		key := field.Name
		out[key] = v.Field(i).Interface()
	}

	return out
}
func (*ReflectUtilTool) Copy(toValue interface{}, fromValue interface{}) {
	err := copier.Copy(&toValue, &fromValue)
	if err != nil {
		panic(base2.NewBsfError2("ReflectUtilTool.Copy出错", err))
	}
}
func (m *ReflectUtilTool) GetTypeName(v interface{}) string {
	t := m.GetType(v)
	return t.Name()
}
func (*ReflectUtilTool) GetType(v interface{}) reflect.Type {
	t := reflect.TypeOf(v)
	// 处理指针类型
	if t.Kind() == reflect.Ptr {
		return t.Elem()
	}
	return t
}
func (m *ReflectUtilTool) GetMethodsMap(obj interface{}) map[string]reflect.Method {
	typ := reflect.TypeOf(obj)
	typ.PkgPath()
	valueMethods := map[string]reflect.Method{}
	for i := 0; i < typ.NumMethod(); i++ {
		valueMethods[typ.Method(i).Name] = typ.Method(i)
	}
	return valueMethods
}
func (*ReflectUtilTool) GetPackages(pkgPaths []string) []*packages.Package {
	cfg := &packages.Config{
		Mode: packages.NeedName | packages.NeedFiles | packages.NeedImports | packages.NeedDeps,
	}
	pkgs, err := packages.Load(cfg, pkgPaths...)
	if err != nil {
		panic(base2.NewBsfError2("注册路由时扫描包出错", err))
	}
	return pkgs
}

func (*ReflectUtilTool) GetStructTypesOfPackage(pkg *packages.Package) []*types.TypeName {
	//获取包下所有类型
	var structTypes []*types.TypeName
	// 遍历包作用域中的所有声明
	scope := pkg.Types.Scope()
	for _, name := range scope.Names() {
		obj := scope.Lookup(name)
		// 检查是否是类型声明
		if typeName, ok := obj.(*types.TypeName); ok {
			// 检查是否是结构体类型
			if _, isStruct := typeName.Type().Underlying().(*types.Struct); isStruct {
				structTypes = append(structTypes, typeName)
			}
		}
	}
	return structTypes
}
